#include "util.hpp"
#include <cstdio>
#include "Protocol.hpp"

volatile bool quit = false;

static void Usage(std::string proc)
{
    std::cerr<<"Usage:\n\t" << proc <<" serverIp serverPort " <<std::endl;
    std::cerr<<"example:\n\t" << proc <<" 127.0.0.1 8081\n" <<std::endl;
}

int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    std::string serverIp = argv[1]; 
    uint16_t serverPort = atoi(argv[2]);
    // 1.创建socket SOCK_STREAM
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0)
    {
        std::cout << " socket : " <<strerror(errno) << std::endl;
        exit(SOCKET_ERR);
    }
    // 2. 需要bind吗? 需要 但是不需要自己显示bind ! 不要自己bind !!
    // 3. 需要listen 吗? 不需要的！
    // 4. 需要accept 吗? 不需要 ！！

    // 2.发起请求 connect 那么向谁发起请求呢?
    // 2.1 先填充需要连接远端主机的基本信息
    struct sockaddr_in server;
    memset(&server,0,sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(serverPort);
    inet_aton(serverIp.c_str(),&server.sin_addr);
    // 2.2 发起请求 connect会自动帮我们进行bind
    if(connect(sock,(const struct sockaddr*)&server,sizeof(server)) != 0)
    {
        std::cerr <<"connect:" << strerror(errno) << std::endl;
        exit(CONN_ERR);
    }

    std::cout <<"info : connect success "<< sock << std::endl;  
    std::string message;
    while(!quit)
    {
        message.resize(0);
        std::cout<<"请输入表达式# ";//1 + 1
        std::getline(std::cin,message);//不会带 \n
        if(strcasecmp(message.c_str(),"quit") == 0) 
        {
            quit = true;
            continue;
        }

        Request req;
        std::string package;
        req.serialize(&package); //1 + 1
        package = encode(package,package.size());
        ssize_t s= write(sock,message.c_str(),message.size());
        if(s>0)
        {
            char buff[1024];
            ssize_t s =read(sock,buff,sizeof(buff) -1 );
            if(s>0) buff[s] = 0;
            std::string echoPackage = buff;
            Response resp;
            uint32_t len = 0;
            std::string tmp = decode(echoPackage,&len);
            if(len > 0)
            {
                echoPackage =  tmp;
                resp.deserialize(echoPackage);
                printf("[exitcode: %d] %d\n",resp.exitCode_,resp.result_);
            }
        }
        else if(s <= 0)
        {
            break;
        }
    }

    close(sock);
    return 0;
}